/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.p4;

import java.util.ArrayList;

import com.example.p4.R;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.os.Bundle;
import android.widget.TextView;

/**
 * SnakeView: implementation of a simple game of Snake
 */
@TargetApi(10)
public class FallingBallsView extends View {

	Paint paint = new Paint();
	
	protected int screenWidth;
    protected int screenHeight;
    
    Bitmap[] images;
    
    protected ArrayList<Ball> balls;
	
    /**
     * Labels for the drawables that will be loaded into the TileView class
     */
	
    private static final int BLUE_BALLOON = 1;
    private static final int RED_BALLOON = 2;
    private static final int YELLOW_BALLOON = 3;
    private static final int TIME_BAR = 4;
    private static final int TIME_BAR_BACK = 5;
    private static final int BGR = 6;
    private static final int WIN = 7;
    private static final int LOSE = 8;
    
    
    public static final int MODE_RUNNING = 1;
    public static final int MODE_WIN = 2;
    public static final int MODE_LOSE = 3;
    
    //Current game mode
    public int mode = MODE_RUNNING;

    //Number of maze levels deep
    protected static int numOfLevels = 3;
    
    //Level height in tiles
    protected int levelHeight = 0;
    
    //Current depth of player's mouse
    protected int currentLevel = 0;
    
    //Last valid point that the user "touched"
    protected Coordinate lastValidPoint = new Coordinate(0,0);
    
    //Progress Bar Images
    protected Drawable progressBar;
    protected Drawable progressBarBack;
    
    //Time left in game
    
    public double progressBarPercent = 0;
    /**
     * mScore: used to track the number of apples captured mMoveDelay: number of
     * milliseconds between snake movements. This will decrease as apples are
     * captured.
     */
    long mScore = 0;
    /**
     * mStatusText: text shows to the user in some run states
     */
    TextView mStatusText;

    /**
     * mSnakeTrail: a list of Coordinates that make up the snake's body
     * mAppleList: the secret location of the juicy apples the snake craves.
     */
    protected ArrayList<Coordinate> touchTrail = new ArrayList<Coordinate>();

    /**
     * Constructs a SnakeView based on inflation from XML
     */
    public FallingBallsView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initSnakeView();
   }

    public FallingBallsView(Context context, AttributeSet attrs, int defStyle) {
    	super(context, attrs, defStyle);
    	initSnakeView();
    }
    
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    	
    	h-=70; //Make room for Progress Bar at bottom of screen
    	screenWidth = w;
    	screenHeight = h;
    	
        clearScreen();
    }
    
    void setScreenResolution(int h, int w)
    {
    	h-=70; //Make room for Progress Bar at bottom of screen
    	screenWidth = w;
    	screenHeight = h;
    	
        clearScreen();
    }
    
    public void clearScreen()
    {
    	//Clear drawable objects?
    }
    
    public void loadSizedTile(int key, Drawable tile, int x, int y)
    {
    	Bitmap bitmap = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        tile.setBounds(0, 0, x, y);
        tile.draw(canvas);
        
        //Do something with bitmap...
        images[key] = bitmap;
    }
    
    public int getBallWidth()
    {
    	return images[BLUE_BALLOON].getWidth();
    }
    
    public int getBallHeight()
    {
    	return images[BLUE_BALLOON].getHeight();
    }
    
    void initSnakeView() {
        setFocusable(true);
    }
    
    private void resetImages(int numOfImages)
    {
    	images = new Bitmap[numOfImages];
    }
    
    public void resetBalls(int numOfBalls)
    {
    	balls = new ArrayList<Ball>();
    	
    	int offset = (screenWidth/numOfBalls);
    	
    	for(int i=0; i<numOfBalls; i++)
    	{
    		int x = (offset*i) + (offset/4);
    		int y = (int) (Math.random()*screenHeight);
    		double dX = (Math.random()*3); 
    		double dY = (Math.random()*12);
    		if(Math.random() > 0.5)
    			dY = -dY;
    		if(Math.random() > 0.5)
    			dX = -dX;
    		
    		int imageIndex = (int)(Math.random()*3) + 1;
    		balls.add(new Ball(x, y, dX, dY, imageIndex));
    	}
    }
    
    private void initImages()
    {
    	
    	 int balloonWidth = screenWidth/6;
    	 int balloonHeight = (int)(balloonWidth*1.25);
    	 
    	 resetImages(9);
    	 Resources r = this.getContext().getResources();
    	 loadSizedTile(BLUE_BALLOON,  r.getDrawable(R.drawable.fallingballs_blueballoon),   balloonWidth, balloonHeight);
    	 loadSizedTile(RED_BALLOON,   r.getDrawable(R.drawable.fallingballs_redballoon),    balloonWidth, balloonHeight);
    	 loadSizedTile(YELLOW_BALLOON,r.getDrawable(R.drawable.fallingballs_yellowballoon), balloonWidth, balloonHeight);
         loadSizedTile(TIME_BAR,      r.getDrawable(R.drawable.progressbar),                screenWidth, 70);
         loadSizedTile(TIME_BAR_BACK, r.getDrawable(R.drawable.bright),                     screenWidth, 70);
         loadSizedTile(BGR,           r.getDrawable(R.drawable.fallingballs_bgr),           screenWidth, screenHeight);
         loadSizedTile(WIN,           r.getDrawable(R.drawable.checkmark),                  screenWidth, screenHeight);
         loadSizedTile(LOSE,          r.getDrawable(R.drawable.xmark),                      screenWidth, screenHeight);
         
         progressBar =     (r.getDrawable(R.drawable.progressbar));
         progressBarBack = (r.getDrawable(R.drawable.bright));
         
         progressBar.setBounds    (0, screenHeight, screenWidth, screenHeight+70);
         progressBarBack.setBounds(0, screenHeight, screenWidth, screenHeight+70);
    }

    void initNewGame(int numberOfBalloons) {
    	setFocusable(true);
    	
        touchTrail.clear();
        
        resetBalls(numberOfBalloons);
        
        initImages();
    }
    
    void resetGame()
    {
    	touchTrail = new ArrayList<Coordinate>();
    	lastValidPoint = new Coordinate(0,0);
    	progressBarPercent = 0;
    	Log.d("GameEvent", "Resetting game");
    }

    /**
     * Save game state so that the user does not lose anything
     * if the game process is killed while we are in the 
     * background.
     * 
     * @return a Bundle with this view's state
     */
    public Bundle saveState() {
        Bundle map = new Bundle();
        map.putLong("mScore", Long.valueOf(mScore));
        return map;
    }
    
    void updateTrail()
    {
    	if(touchTrail.size() == 0)
    		return;
    	
    	lastValidPoint = touchTrail.get(touchTrail.size()-1);
    }

    public void drawProgressBar(Canvas canvas)
    {
    	paint.setColor(Color.DKGRAY);
        if(progressBarBack != null){
        	progressBarBack.draw(canvas);
        	
        	Rect rect = progressBarBack.getBounds();
        	int barWidth = (int)(screenWidth*.92);
        	canvas.drawRect((float) ((barWidth - (barWidth*progressBarPercent))), rect.top, rect.right, rect.bottom, paint);
        }
        if(progressBar != null)
        	progressBar.draw(canvas);
    }
    
    @Override
    public void onDraw(Canvas canvas) {
    	
    	if(images != null)
    	{
    		drawBackground(canvas);
    		drawBalls(canvas);
    		drawWinOrLose(canvas);
    	}
        drawProgressBar(canvas);
        
        super.onDraw(canvas);
    }
    
    private void drawWinOrLose(Canvas canvas)
    {
    	if(mode == MODE_WIN)
    		canvas.drawBitmap(images[WIN], 0, 0, paint);
    	else if(mode == MODE_LOSE)
    		canvas.drawBitmap(images[LOSE], 0, 0, paint);
    }
    
    public void setMode(int newMode)
    {
    	mode = newMode;
    }
    
    private void drawBackground(Canvas canvas)
    {
    	canvas.drawBitmap(images[BGR], 0, 0, paint);
    }
    
    public void drawBalls(Canvas canvas)
    {
    	for(int i=0; i<balls.size(); i++)
    	{
    		canvas.drawBitmap(images[balls.get(i).imageIndex], balls.get(i).x, balls.get(i).y, paint);
    	}
    	
    }

    
    /**
     * Simple class containing two integer values and a comparison function.
     * There's probably something I should use instead, but this was quick and
     * easy to build.
     * 
     */
    public class Coordinate {
        public int x;
        public int y;

        public Coordinate(int newX, int newY) {
            x = newX;
            y = newY;
        }

        public boolean equals(Coordinate other) {
            if (x == other.x && y == other.y) {
                return true;
            }
            return false;
        }

        @Override
        public String toString() {
            return "Coordinate: [" + x + "," + y + "]";
        }
    }
    
    public class Ball extends Coordinate
    {
    	public Ball(int newX, int newY, double newdX, double newdY, int newImageIndex) {
			super(newX, newY);
			dX = newdX;
			dY = newdY;
			imageIndex = newImageIndex;
		}
		public double dX;
    	public double dY;
    	public int imageIndex;
    	
    	public void move(int lowX, int lowY, int highX, int highY)
    	{
    		if(x+dX < lowX)
    		{
    			x = lowX;
    			dX = -dX;
    		}
    		else if(x+dX > highX)
    		{
    			x = highX;
    			dX = -dX;
    		}
    		else
    			x += dX;
    		
    		if(y+dY < lowY)
    		{
    			y = lowY;
    			dY = -dY;
    		}
    		else if(y+dY > highY)
    		{
    			y = highY;
    			dY = -dY;
    		}
    		else
    			y += dY;
    	}
    }

	public void addTouchPoint(int tileX, int tileY) {
		touchTrail.add(new Coordinate(tileX, tileY));
	}

    
}
